Link wasm-wasm directly in the fuzzer#8794
Conversation
|
Emscripten also has some complexity around the original exports and the instrumented ones, which I also am not totally sure I follow, |
|
I can't seem to find the conversation, but IIRC one of the other v8 folks said that the wrapped version should behave the same as the original. Maybe a bug in v8? I can poke around a bit more on it tomorrow. |
|
Thanks, then let me reduce my testcase here, and I'll get that to you. |
|
Ok, here is the testcase: https://gist.github.com/kripken/1759e0f618e0a755e5a69f28f6b78142 $ diff -U2 a.js b.js
--- a.js 2026-06-01 16:41:32.078358653 -0700
+++ b.js 2026-06-01 16:41:33.662363189 -0700
@@ -203,5 +203,4 @@
// whose keys are strings and whose values are the corresponding exports).
var exports = {};
-var rawExports = {};
// Also track exports in a list, to allow access by index. Each entry here will
@@ -520,5 +519,5 @@
assert(secondBinary);
// Provide the primary module's exports to the secondary.
- imports['primary'] = rawExports;
+ imports['primary'] = exports;
}
@@ -554,5 +553,4 @@
var key = e.name;
var value = instance.exports[key];
- rawExports[key] = value;
value = wrapExportForJSPI(value);
exports[key] = value;The only diff between the JS files is to use the raw exports as the imports of the other module. And the behavior is very different: versus The start function in the second module is important somehow - I only see this when fuzzing start functions. |
|
I updated the gist with a browser version in By commenting/uncommenting the lines here, the different behavior can be seen: // Provide the primary module's exports to the secondary.
//imports['primary'] = exports;
imports['primary'] = rawExports;What happens here is that we instantiate a second wasm file, with imports from the first. That second wasm file's start function is actually an imported function from the first. If it is wrapped for JSPI, behavior is very different. If not wrapped, this is the result: If wrapped, this: It looks like when it is not wrapped, the error during the start function (i.e. during instantiation of the second module) happens asynchronously - later, after the script continues on to running the exports. And when it is wrapped, we synchronously experience the start function's error, halting the script right there. If this is not a browser bug, then the latter behavior is what we want in our fuzzer I think? |
|
Btw my motivation for testing this in a browser was to compare browsers. But in Firefox (with the JSPI flag set) I get this: Perhaps the JSPI impl there is incomplete? |
This avoids passing JSPI-wrapped exports from one wasm module as the imports
to another. Without this, the stack traces and erroring behavior become very
confusing. I noticed this during #8736 (fuzzing start) but I don't think it's limited to
the start function.
With that said, I admit I don't totally understand why the stack traces etc. get
very odd before this PR... async stuff is complex. But this seems like the right
thing anyhow?